package org.light.simpleauth.verb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.light.core.Verb;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.FieldSerialComparator;
import org.light.domain.JavascriptBlock;
import org.light.domain.JavascriptMethod;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.Type;
import org.light.easyui.EasyUIPositions;
import org.light.exception.ValidateException;
import org.light.utils.FieldUtil;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;
import org.light.verb.FindById;
import org.light.verb.Update;

public class UpdateMyProfileUser extends Verb implements EasyUIPositions {

	@Override
	public Method generateDaoImplMethod() throws Exception {
		return null;
	}	

	@Override
	public Method generateDaoMethodDefinition() throws Exception {
		return null;
	}

	@Override
	public Method generateServiceMethodDefinition() throws Exception {
		return null;
	}

	@Override
	public Method generateServiceImplMethod() throws Exception  {
		return null;
	}
	
	public UpdateMyProfileUser(Domain domain,Set<Field> deniedFields) throws ValidateException{
		super();
		this.domain = domain;
		this.deniedFields = deniedFields;
		this.setVerbName("UpdateMyProfile"+StringUtil.capFirst(this.domain.getStandardName()));
		this.setLabel("更新自己资料");
		if  (domain.getLanguage().equalsIgnoreCase("english"))  this.setLabel("Update My Profile User");
	}

	@Override
	public Method generateControllerMethod() throws Exception {
		if (this.denied) return null;
		else {
			Method method = new Method();
			method.setStandardName("processRequest");
			method.setReturnType(new Type("void"));
			method.setThrowException(true);
			List<String> list = new ArrayList<String>();
			list.add("ServletException");
			list.add("IOException");
			method.setIsprotected(true);
			method.setOtherExceptions(list);
			method.addSignature(new Signature(1,"request",new Type("HttpServletRequest","javax.servlet.http")));
			method.addSignature(new Signature(2,"response",new Type("HttpServletResponse","javax.servlet.http")));
			method.addAdditionalImport("java.io.IOException");
			method.addAdditionalImport("java.io.PrintWriter");
			method.addAdditionalImport("javax.servlet.ServletException");
			method.addAdditionalImport("javax.servlet.http.HttpServlet");
			method.addAdditionalImport("javax.servlet.http.HttpServletRequest");
			method.addAdditionalImport("javax.servlet.http.HttpServletResponse");
			method.addAdditionalImport("java.util.Map");
			method.addAdditionalImport("java.util.TreeMap");
			method.addAdditionalImport("net.sf.json.JSONObject");
			method.addAdditionalImport("javax.servlet.http.HttpSession");
			method.addAdditionalImport("java.io.BufferedReader");
			method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getDomainSuffix()+"."+this.domain.getCapFirstDomainNameWithSuffix());
			method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceSuffix()+"."+this.domain.getStandardName()+"Service");
			method.addAdditionalImport(this.domain.getPackageToken()+"."+this.domain.getServiceimplSuffix()+"."+this.domain.getStandardName()+"ServiceImpl");
			
			Set<Field> deniedFields = new TreeSet<>();
			deniedFields.add(this.domain.findFieldByFixedName("password"));
			deniedFields.add(this.domain.findFieldByFixedName("salt"));
			deniedFields.add(this.domain.findFieldByFixedName("loginFailure"));
			
			List<Writeable> sList = new ArrayList<Writeable>();
			long serial = 1000L;
			sList.add(new Statement(serial+1000L,2,"response.setContentType(\"application/json;charset=UTF-8\");"));
			sList.add(new Statement(serial+2000L,2,"PrintWriter out = response.getWriter();"));
			sList.add(new Statement(serial+3000L,2,"Map<String,Object> result = new TreeMap<String,Object>();"));
			sList.add(new Statement(serial+4000L,2,"try {"));
			sList.add(new Statement(serial+5000L,3,"StringBuilder jsonBuilder = new StringBuilder();"));
			sList.add(new Statement(serial+6000L,3,"BufferedReader reader = request.getReader();"));
			sList.add(new Statement(serial+7000L,3,"String line;"));
			sList.add(new Statement(serial+8000L,3,"while ((line = reader.readLine()) != null) {"));
			sList.add(new Statement(serial+9000L,4,"jsonBuilder.append(line);"));
			sList.add(new Statement(serial+10000L,3,"}"));
			sList.add(new Statement(serial+11000L,3,"String jsonString = jsonBuilder.toString();"));
			sList.add(new Statement(serial+12000L,3,"JSONObject jsonReq = JSONObject.fromObject(jsonString);"));
			sList.add(new Statement(serial+13000L,0,""));
			sList.add(new Statement(serial+14000L,3,"HttpSession session = request.getSession();"));
			sList.add(new Statement(serial+15000L,3,this.domain.getCapFirstDomainNameWithSuffix()+" "+this.domain.getLowerFirstDomainName()+" = ("+this.domain.getCapFirstDomainNameWithSuffix()+") session.getAttribute(\"user\");"));

			serial += 16000L;
			for (Field f : domain.getFieldsWithoutId()){
				if (!deniedFields.contains(f)&& !"image".equalsIgnoreCase(f.getFieldType())){
					sList.add(new Statement(serial,3,StringUtil.lowerFirst(domain.getStandardName())+".set"+StringUtil.capFirst(f.getFieldName())+"("+FieldUtil.generateRequestGetJsonParameterString(f)+");"));
					serial += 1000L;
				}
			}

			sList.add(new Statement(serial+29000L,3,this.domain.getCapFirstDomainName()+"Service service = new "+this.domain.getCapFirstDomainName()+"ServiceImpl();"));
			FindById findUser = new FindById(this.domain);
			sList.add(new Statement(serial+30000L,3,this.domain.getCapFirstDomainNameWithSuffix()+" ori"+this.domain.getCapFirstDomainName()+" = service."+StringUtil.lowerFirst(findUser.getVerbName())+"("+this.domain.getLowerFirstDomainName()+".get"+this.domain.getDomainId().getCapFirstFieldName()+"());"));
			
			serial += 31000L;
			boolean imageExists = this.domain.containsImage();
			for (Field f:this.domain.getPlainFields()) {
				if (f.getFieldType().equalsIgnoreCase("image")) {
					imageExists = true;
					sList.add(new Statement(serial,3,"if (ori"+this.domain.getCapFirstDomainName()+".get"+f.getCapFirstFieldName()+"()!=null) {"));
					sList.add(new Statement(serial+1000L,4,this.domain.getLowerFirstDomainName()+".set"+f.getCapFirstFieldName()+"(ori"+this.domain.getCapFirstDomainName()+".get"+f.getCapFirstFieldName()+"());"));
					sList.add(new Statement(serial+2000L,3,"}"));
					serial += 3000L;
				}				
			}
			for (Field f:this.domain.getPlainFields()) {
				if (f.getFieldType().equalsIgnoreCase("image")) {
					sList.add(new Statement(serial,3,"if ("+this.domain.getCapFirstDomainName()+"ServiceImpl.temp"+this.domain.getCapFirstDomainName()+"!=null && "+this.domain.getCapFirstDomainName()+"ServiceImpl.temp"+this.domain.getCapFirstDomainName()+".get"+f.getCapFirstFieldName()+"()!=null) {"));
					sList.add(new Statement(serial+1000L,4,this.domain.getLowerFirstDomainName()+".set"+f.getCapFirstFieldName()+"("+this.domain.getCapFirstDomainName()+"ServiceImpl.temp"+this.domain.getCapFirstDomainName()+".get"+f.getCapFirstFieldName()+"());"));
					sList.add(new Statement(serial+2000L,3,"}"));
					serial += 3000L;
				}				
			}
			if (imageExists) 
			{
				sList.add(new Statement(serial+1000L,3,this.domain.getCapFirstDomainName()+"ServiceImpl.temp"+this.domain.getCapFirstDomainName()+" = new  "+this.domain.getCapFirstDomainNameWithSuffix()+"();"));
				serial += 2000L;
			}

			Update updateUser = new Update(this.domain);
			sList.add(new Statement(serial+44000L,3,"boolean success = service."+StringUtil.lowerFirst(updateUser.getVerbName())+"("+this.domain.getLowerFirstDomainName()+");"));
			sList.add(new Statement(serial+45000L,3,"result.put(\"success\",success);"));
			sList.add(new Statement(serial+46000L,3,"result.put(\"data\",null);"));
			sList.add(new Statement(serial+47000L,3,"out.print(JSONObject.fromObject(result).toString());"));
			sList.add(new Statement(serial+48000L,2,"} catch (Exception e){"));
			sList.add(new Statement(serial+49000L,3,"e.printStackTrace();"));
			sList.add(new Statement(serial+50000L,3,"result.put(\"success\",false);"));
			sList.add(new Statement(serial+51000L,3,"result.put(\"reason\",e.getMessage());"));
			sList.add(new Statement(serial+52000L,3,"out.print(JSONObject.fromObject(result).toString());"));
			sList.add(new Statement(serial+53000L,2,"} finally {"));
			sList.add(new Statement(serial+54000L,3,"out.close();"));
			sList.add(new Statement(serial+55000L,2,"}"));
			
			method.setMethodStatementList(WriteableUtil.merge(sList));		
			return method;
		}
	}

	@Override
	public JavascriptBlock generateEasyUIJSButtonBlock() throws Exception {
		return null;
	}

	@Override
	public JavascriptMethod generateEasyUIJSActionMethod() throws Exception {
		if (this.denied) return null;
		else {
			Domain domain = this.domain;
			JavascriptMethod method = new JavascriptMethod();
			method.setSerial(200);
			method.setStandardName(StringUtil.lowerFirst(this.getVerbName()));
			
			List<Writeable> sList = new ArrayList<Writeable>();

			sList.add(new Statement(1000L,1,"if (isBlank($(\"#ff\").find(\"#"+this.domain.findFieldByFixedName("userName").getLowerFirstFieldName()+"\").val())){"));
			if ("english".equalsIgnoreCase(this.domain.getLanguage())) {
				sList.add(new Statement(2000L,2,"$.messager.alert(\"Error\",\"Field "+this.domain.findFieldByFixedName("userName").getText() +"is empty.\",\"error\");"));
			} else {
				sList.add(new Statement(2000L,2,"$.messager.alert(\"错误\",\"必须字段"+this.domain.findFieldByFixedName("userName").getText()+"为空！\",\"error\");"));
			}
			sList.add(new Statement(3000L,2,"return;"));
			sList.add(new Statement(4000L,1,"}"));
			sList.add(new Statement(5000L,1,"$.ajax({"));
			sList.add(new Statement(6000L,2,"type: \"post\","));
			sList.add(new Statement(7000L,2,"url: \"../"+ this.domain.getControllerPackagePrefix()+"profile"+this.domain.getControllerNamingSuffix()+"/"+StringUtil.lowerFirst(this.getVerbName())+"\","));
			sList.add(new Statement(8000L,2,"data: JSON.stringify({"));
			
			long serial = 9000L;
			Set<Field> normalFields = new TreeSet<>(new FieldSerialComparator());
			normalFields.addAll(domain.getFieldsWithoutIdAndActive());
			Set<Field> deniedFields = new TreeSet<>(new FieldSerialComparator());
			deniedFields.add(this.domain.findFieldByFixedName("password"));
			deniedFields.add(this.domain.findFieldByFixedName("salt"));
			deniedFields.add(this.domain.findFieldByFixedName("loginFailure"));
			normalFields = FieldUtil.filterDeniedFields(normalFields,deniedFields);
			for (Field f: normalFields){
				if (f instanceof Dropdown) {
					sList.add(new Statement(serial, 3, f.getLowerFirstFieldName() + ":parseIntNeg($(\"#ff\").find(\"#"
							+ f.getLowerFirstFieldName() + "\").combobox(\"getValue\")),"));
				} else if (f.getFieldType().equalsIgnoreCase("bool")) {
					sList.add(new Statement(serial, 3,
							f.getLowerFirstFieldName() + ":parseBoolean($(\"#ff\").find(\"input[name='"
									+ f.getLowerFirstFieldName() + "']:checked\").val()),"));
				}  else if (f.getFieldType().equalsIgnoreCase("i32")||f.getFieldType().equalsIgnoreCase("i64")) {
					sList.add(new Statement(serial, 3, f.getLowerFirstFieldName() + ":parseInt($(\"#ff\").find(\"#"
							+ f.getLowerFirstFieldName() + "\").val()),"));
				} else if (f.getFieldType().equalsIgnoreCase("f64")||f.getFieldType().equalsIgnoreCase("f32")) {
					sList.add(new Statement(serial, 3, f.getLowerFirstFieldName() + ":parseFloat($(\"#ff\").find(\"#"
							+ f.getLowerFirstFieldName() + "\").val()),"));
				} else if (f.isTextarea()) {
					sList.add(new Statement(serial, 3, f.getLowerFirstFieldName() + ":$(\"#ff\").find(\"#"
							+ f.getLowerFirstFieldName() + "\").val(),"));
				} else {
					sList.add(new Statement(serial, 3, f.getLowerFirstFieldName() + ":$(\"#ff\").find(\"#"
							+ f.getLowerFirstFieldName() + "\").val(),"));
				}
				serial+=1000;
			}
			if (this.domain.hasActiveField()) {
				sList.add(new Statement(serial,3, this.domain.getActive().getLowerFirstFieldName()+":parseBoolean($(\"#ff\").find(\"input[name='"+this.domain.getActive().getLowerFirstFieldName()+"']:checked\").val()),"));
			}
			
			sList.add(new Statement(serial+26000L,2,"}),"));
			sList.add(new Statement(serial+27000L,2,"dataType: 'json',"));
			sList.add(new Statement(serial+28000L,2,"contentType:\"application/json;charset=UTF-8\","));
			sList.add(new Statement(serial+29000L,2,"success: function(data, textStatus) {"));
			sList.add(new Statement(serial+30000L,3,"if (data.success) {"));
			sList.add(new Statement(serial+31000L,4,"$('#ff').form('clear');"));
			FindMyProfileUser find = new FindMyProfileUser(this.domain,null);
			if ("english".equalsIgnoreCase(this.domain.getLanguage())) {
				sList.add(new Statement(serial+32000L,4,"$.messager.alert(\"Info\",\"Update "+this.domain.getText()+" profile succeed.\",\"info\");"));
				sList.add(new Statement(serial+32100L,4,StringUtil.lowerFirst(find.getVerbName())+"();"));
				sList.add(new Statement(serial+33000L,3,"} else if (data.success == false){"));
				sList.add(new Statement(serial+34000L,4,"$.messager.alert(\"Error\",\"Update "+this.domain.getText()+" profile failed.\",\"error\");"));
				sList.add(new Statement(serial+34100L,4,StringUtil.lowerFirst(find.getVerbName())+"();"));
			} else {
				sList.add(new Statement(serial+32000L,4,"$.messager.alert(\"信息\",\"更新用户资料成功！\",\"info\");"));
				sList.add(new Statement(serial+32100L,4,StringUtil.lowerFirst(find.getVerbName())+"();"));
				sList.add(new Statement(serial+33000L,3,"} else if (data.success == false){"));
				sList.add(new Statement(serial+34000L,4,"$.messager.alert(\"错误\",\"更新用户资料失败！\",\"error\");"));
				sList.add(new Statement(serial+34100L,4,StringUtil.lowerFirst(find.getVerbName())+"();"));
			}
			sList.add(new Statement(serial+35000L,3,"}"));
			sList.add(new Statement(serial+36000L,3,"},"));
			sList.add(new Statement(serial+37000L,2,"complete : function(XMLHttpRequest, textStatus) {"));
			sList.add(new Statement(serial+38000L,2,"},"));
			sList.add(new Statement(serial+39000L,2,"error : function(XMLHttpRequest,textStatus,errorThrown) {"));
			sList.add(new Statement(serial+40000L,3,"alert(\"Error:\"+textStatus);"));
			sList.add(new Statement(serial+41000L,3,"alert(errorThrown.toString());"));
			sList.add(new Statement(serial+42000L,2,"}"));
			sList.add(new Statement(serial+43000L,1,"});"));
			
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;	
		}
	}

	@Override
	public Method generateDummyDaoImplMethod() throws Exception {
		return null;
	}

	@Override
	public Method generateDummyServiceImplMethod() throws Exception {
		return null;
	}

	@Override
	public Method generateDummyDaoMethodDefinition() throws Exception {
		return null;
	}
}
